package com.bete.updata;

import android.net.Uri;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.FileNameMap;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.concurrent.TimeUnit;

import me.jessyan.autosize.utils.LogUtils;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;


public class OkhttpDonloadUtil {

    private static OkhttpDonloadUtil uploadUtil;
    private final OkHttpClient.Builder okHttpClientBuilder;

    public static OkhttpDonloadUtil getInstance() {
        if (uploadUtil == null) {
            uploadUtil = new OkhttpDonloadUtil();
        }
        return uploadUtil;
    }

    private OkhttpDonloadUtil() {
        okHttpClientBuilder = new OkHttpClient().newBuilder();
    }

    private static final MediaType MEDIA_TYPE_ZIP = MediaType.parse("application/zip; charset=utf-8");
    private static final MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/x-markdown; charset=utf-8");
    private static final MediaType MEDIA_TYPE_OBJECT = MediaType.parse("application/octet-stream");

    public static RequestBody createCustomRequestBody(final MediaType contentType, final File file, final ProgressListener listener) {
        return new RequestBody() {
            @Override
            public MediaType contentType() {
                return contentType;
            }

            @Override
            public long contentLength() {
                return file.length();
            }

            @Override
            public void writeTo(BufferedSink sink) throws IOException {
                Source source;
                try {
                    source = Okio.source(file);
                    //sink.writeAll(source);
                    Buffer buf = new Buffer();
                    Long remaining = contentLength();
                    for (long readCount; (readCount = source.read(buf, 2048)) != -1; ) {
                        sink.write(buf, readCount);
                        listener.onProgress(contentLength(), remaining -= readCount, remaining == 0);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
    }

    public String put(MediaType mediaType, String uploadUrl, String localPath) throws IOException {
        File file = new File(localPath);
        RequestBody body = RequestBody.create(mediaType, file);
        Request request = new Request.Builder()
                .url(uploadUrl)
                .put(body)
                .build();
        //修改各种 Timeout
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(600, TimeUnit.SECONDS)
                .readTimeout(200, TimeUnit.SECONDS)
                .writeTimeout(600, TimeUnit.SECONDS)
                .build();
        //如果不需要可以直接写成 OkHttpClient client = new OkHttpClient.Builder().build();

        Response response = client
                .newCall(request)
                .execute();
        return response.body().string() + ":" + response.code();
    }

    public interface ProgressListener {
        void onProgress(long totalBytes, long remainingBytes, boolean done);
    }

    public interface OnUploadListener {
        /**
         * 下载成功
         */
        void onUploadSuccess();

        /**
         * @param progress 下载进度
         */
        void onUploadding(int progress);

        /**
         * 下载失败
         */
        void onUploadFailed();
    }

    private static OkHttpClient client;

    /**
     * 创建一个OkHttpClient的对象的单例
     *
     * @return
     */
    private synchronized static OkHttpClient getOkHttpClientInstance() {
        if (client == null) {
            OkHttpClient.Builder builder = new OkHttpClient.Builder()
                    //设置连接超时等属性,不设置可能会报异常
                    // 超时时间
                    .connectTimeout(120, TimeUnit.SECONDS)
                    // 读取的超时时间
                    .readTimeout(120, TimeUnit.SECONDS)
                    // 写入的超时时间
                    .writeTimeout(120, TimeUnit.SECONDS)
                    .retryOnConnectionFailure(true);

            client = builder.build();
        }
        return client;
    }

    /**
     * 获取文件MimeType
     *
     * @param filename
     * @return
     */
    private static String getMimeType(String filename) {
        FileNameMap filenameMap = URLConnection.getFileNameMap();
        String contentType = filenameMap.getContentTypeFor(filename);
        if (contentType == null) {
            contentType = "application/octet-stream"; //* exe,所有的可执行程序
        }
        return contentType;
    }


    /**
     * 获得Request实例(不带进度)
     *
     * @param url
     * @return
     */
    private static Request getRequest(String url, String uploadPath, List<String> fileNames) {
        Request.Builder builder = new Request.Builder();
        builder.url(url)
                .post(getRequestBody(uploadPath, fileNames));
        return builder.build();
    }

    /**
     * 获得Request实例(不带进度)
     *
     * @param url
     * @return
     */
    private static Request getRequest(String url) {
//        Request.Builder builder = new Request.Builder();
//        // https://ucan.25pp.com/PPAssistant_PP_103.apk
//        HttpUrl build = new HttpUrl.Builder()
//                .host("https://ucan.25pp.com/PPAssistant_PP_103.apk")
//                .build();
//        builder.url(url)
//                .post(getRequestBody(uploadPath));
        //        builder.url(url)
//                .post(getRequestBody(uploadPath));

        Request build = new Request.Builder()
                .url(url)
                .build();


        return build;
    }

    /**
     * 通过上传的文件的完整路径生成RequestBody
     *
     * @param fileNames 完整的文件路径
     * @return
     */
    private static RequestBody getRequestBody(String uploadPath, List<String> fileNames) {
        //创建MultipartBody.Builder，用于添加请求的数据
        MultipartBody.Builder builder = new MultipartBody.Builder();
        for (int i = 0; i < fileNames.size(); i++) { //对文件进行遍历
            File file = new File(fileNames.get(i)); //生成文件
            //根据文件的后缀名，获得文件类型
            String fileType = getMimeType(file.getName());
            builder.addFormDataPart( //给Builder添加上传的文件
                    "file",  //请求的名字
                    uploadPath + file.getName(), //文件的文字，服务器端用来解析的
                    RequestBody.create(MediaType.parse(fileType), file) //创建RequestBody，把上传的文件放入
            );
        }
        return builder.build(); //根据Builder创建请求
    }

    /**
     * 通过上传的文件的完整路径生成RequestBody
     * @return
     */
    private static RequestBody getRequestBody(String uploadPath) {
        //创建MultipartBody.Builder，用于添加请求的数据
        MultipartBody.Builder builder = new MultipartBody.Builder();
        File file = new File(uploadPath); //生成文件
        //根据文件的后缀名，获得文件类型
        String fileType = getMimeType(file.getName());
        builder.addFormDataPart( //给Builder添加上传的文件
                "file",  //请求的名字
                uploadPath, //文件的文字，服务器端用来解析的
                RequestBody.create(MediaType.parse(fileType), file) //创建RequestBody，把上传的文件放入
        );
        return builder.build(); //根据Builder创建请求
    }

    //获取字符串
    public static String getString(Response response) throws IOException {
        if (response != null && response.isSuccessful()) {
            return response.body().string();
        }
        return null;
    }


    public boolean downloadFile(String httpapkurl, String tempHttpDonwnloadFilePath) {
        Request response = getRequest(httpapkurl);
        Call call = getOkHttpClientInstance().newCall(response);
        try {
            Response execute = call.execute();
            // 获取请求结果
            ResponseBody responseBody = execute.body();
            if (null != responseBody) {

                File file = new File(tempHttpDonwnloadFilePath);
                // 判断目录是否存在，不存在则创建目录
                File parent = new File(file.getParent());
                if (!parent.exists()) {
                    parent.mkdir();
                }
                // 判断文件是否存在, 不存在创建文件
                if (!file.exists()) {
                    if (file.createNewFile()) {
                        // 获取请求结果输入流
                        InputStream rInputStream = responseBody.byteStream();

                        // 创建读取字节流的byte数组
                        byte[] buffer = new byte[500];

                        int areRead;

                        // 创建文件输出流
                        FileOutputStream outputStream = new FileOutputStream(file);

                        // 使用输入流读取字节，在输出到文件
                        while ((areRead = rInputStream.read(buffer)) != -1) {
                            outputStream.write(buffer, 0, areRead);
                        }
                        rInputStream.close();
                        outputStream.close();
                    }
                }
            }
            execute.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return true;
    }


    public void downloadFile(String httpapkurl, Callback callback) {
        LogUtils.d(" httpapkurl value is : " + httpapkurl);
        Request request = getRequest(httpapkurl);
        Call call = getOkHttpClientInstance().newCall(request);
        call.enqueue(callback);

    }


}